// Fill out your copyright notice in the Description page of Project Settings.

#include "CPP_SpriteControlComponent.h"

// Sets default values for this component's properties
UCPP_SpriteControlComponent::UCPP_SpriteControlComponent(): OwnerActor(nullptr), PlayerPawn(nullptr), PFComp(nullptr),
                                                            CPP_MovementDir(0),
                                                            CPP_LockToTarget(false)
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}

// Called when the game starts
void UCPP_SpriteControlComponent::BeginPlay()
{
	Super::BeginPlay();
	OwnerActor = GetOwner();
	PFComp = OwnerActor->GetComponentByClass<UPaperFlipbookComponent>();
	if (PFComp) {
		defaultLocation = PFComp->GetRelativeLocation();
		if (!defaultMat)
			defaultMat = PFComp->GetMaterial(0);
	}

	if (const APlayerController* PC = GetWorld()->GetFirstPlayerController())
		PlayerPawn = PC->GetPawn();
	// ...
	
}

void UCPP_SpriteControlComponent::CPP_SetFlip()
{
	// 有精灵时才进行转身
	if (PFComp)
	{
		//// 如果不是玩家，则用速度作为移动方向
		//if (!PFComp->ComponentHasTag("Player"))
		//	MovementDir = ownerActor->GetVelocity().X;
		if (CPP_MovementDir == 0)
		{
			CPP_MovementDir = PFComp->GetRelativeScale3D().X;
			return;
		}

		if (CPP_LockToTarget)
		{
			// 面朝目标方向		
			CPP_MovementDir = (PlayerPawn->GetActorLocation().X - OwnerActor->GetActorLocation().X) > 0 ? 1 : -1;
		} 
		else
		{
			// 面朝移动方向
			CPP_MovementDir = (CPP_MovementDir > 0) - (CPP_MovementDir < 0);
		}

		// 只在移动方向与精灵方向相反时进行转身
		if (PFComp->GetRelativeScale3D().X != CPP_MovementDir)
			PFComp->SetWorldScale3D(FVector3d(CPP_MovementDir, 1, 1));
	}
}

void UCPP_SpriteControlComponent::CPP_HurtFlicker(UPrimitiveComponent* OtherComp)
{
	if (PFComp && OtherComp)
	{
		if (OtherComp->ComponentHasTag(TEXT("AttackBox")))
		{
			// 使用玩家的参数
			UCPP_SpriteControlComponent* PlayerComp = OtherComp->GetOwner()->FindComponentByClass<UCPP_SpriteControlComponent>();
			HurtFlickerDurationTime = PlayerComp->HurtFlickerDurationTime;
			PFComp->SetMaterial(0, LoadObject<UMaterialInterface>(nullptr, TEXT("/Script/Engine.Material'/Game/Materials/EnemyHurtSpriteMaterial.EnemyHurtSpriteMaterial'")));

			GetWorld()->GetTimerManager().SetTimer(
				HurtFlickerDelayHandle,                          // 句柄
				this,                                      // 对象
				&UCPP_SpriteControlComponent::CloseHurtFlicker,          // 函数指针
				HurtFlickerDurationTime,                                      // 延迟秒数
				false                               // 是否循环
			);
		}
	}
}
void UCPP_SpriteControlComponent::CloseHurtFlicker()
{
	GetWorld()->GetTimerManager().ClearTimer(HurtFlickerDelayHandle);
	if (PFComp && defaultMat)
		PFComp->SetMaterial(0, defaultMat);
}

void UCPP_SpriteControlComponent::CloseSpriteFreeze()
{
	GetWorld()->GetTimerManager().ClearTimer(SpriteFreezeDelayHandle);
	if (OwnerActor)
		OwnerActor->CustomTimeDilation = 1.0f;
}

void UCPP_SpriteControlComponent::CPP_SpriteShake(UPrimitiveComponent* OtherComp)
{
	if (PFComp && OtherComp)
	{
		if (OtherComp->ComponentHasTag(TEXT("AttackBox")))
		{
			// 使用玩家的参数
			UCPP_SpriteControlComponent* PlayerComp = OtherComp->GetOwner()->FindComponentByClass<UCPP_SpriteControlComponent>();
			SpriteShakeFrequency = PlayerComp->SpriteShakeFrequency;
			SpriteShakeDurationTime = PlayerComp->SpriteShakeDurationTime;
			GetWorld()->GetTimerManager().SetTimer(
				SpriteShakeLoopHandle,                          // 句柄
				this,                                      // 对象
				&UCPP_SpriteControlComponent::SpriteShakeLoop,          // 函数指针
				SpriteShakeFrequency,                                      // 延迟秒数
				true                               // 是否循环
			);

			// 结束timer
			GetWorld()->GetTimerManager().SetTimer(
				SpriteShakeDelayHandle,                          // 句柄
				this,                                      // 对象
				&UCPP_SpriteControlComponent::CloseSpriteShake,          // 函数指针
				SpriteShakeDurationTime,                                      // 延迟秒数
				false                               // 是否循环
			);
		}
	}
}
void UCPP_SpriteControlComponent::CPP_SpriteFreeze(UPrimitiveComponent* OtherComp)
{
	// 如果不是玩家，被AttackBox砍到，会调用玩家设定的冻结参数
	if (OwnerActor && !OwnerActor->ActorHasTag(TEXT("Player")))
	{
		if (OtherComp && OtherComp->ComponentHasTag(TEXT("AttackBox")))
		{
			UCPP_SpriteControlComponent* PlayerComp = OtherComp->GetOwner()->FindComponentByClass<UCPP_SpriteControlComponent>();
			SpriteFreezetimeScale = PlayerComp->SpriteFreezetimeScale;
			SpriteFreezeDurationTime = PlayerComp->SpriteFreezeDurationTime;
		}
	}
	OwnerActor->CustomTimeDilation = SpriteFreezetimeScale;
	GetWorld()->GetTimerManager().SetTimer(
		SpriteFreezeDelayHandle,                          // 句柄
		this,                                      // 对象
		&UCPP_SpriteControlComponent::CloseSpriteFreeze,          // 函数指针
		SpriteFreezeDurationTime,                                      // 延迟秒数
		false                               // 是否循环
	);
}
void UCPP_SpriteControlComponent::SpriteShakeLoop()
{
	if (PFComp)
	{
		FVector newLocation = FVector(defaultLocation.X + (FMath::FRandRange(-1.0f, 1.0f) * SpriteShakeForce), defaultLocation.Y, defaultLocation.Z + (FMath::FRandRange(-1.0f, 1.0f) * SpriteShakeForce));
		PFComp->SetRelativeLocation(newLocation);
	}
}
void UCPP_SpriteControlComponent::CloseSpriteShake() 
{
	GetWorld()->GetTimerManager().ClearTimer(SpriteShakeLoopHandle);
	GetWorld()->GetTimerManager().ClearTimer(SpriteShakeDelayHandle);
	PFComp->SetRelativeLocation(defaultLocation);
}

// Called every frame
void UCPP_SpriteControlComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	CPP_SetFlip();
	//GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::White, PFComp->GetRelativeScale3D().ToString());

	// ...
}

